<?php

class Materials_Model_Category_Storage_Table extends Workset_Model_Object_Storage_Table_Abstract {

	protected $_objectClass 		= 'Materials_Model_Category';

	protected $_tableClass 			= 'Materials_Table_Category';

	protected $_iteratorClass 		= 'Workset_Model_Object_Iterator';

	protected $_materialObjectClass = 'Materials_Model_Material';

	protected $_materialTableClass = 'Materials_Table_Material';

	protected $_material2CategoryTableClass = 'Materials_Table_Material2Category';

	protected $_object2CatalogueCategoryTableClass = 'Materials_Table_Material2CatalogueCategory';

    function linkToObject(Materials_Model_Category $object, Workset_Model_Object_Interface $refObject) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {

            if ($refObject instanceof Materials_Model_Material) {
                return $row->addDependentRow($this->_material2CategoryTableClass, array(
                    'material_id' => $refObject->getId(),
                ));
            } else {
                throw new Zend_Exception('Undefined reference object type');
            }
        }
    }

    function unlinkObject(Materials_Model_Category $object, Workset_Model_Object_Interface $refObject) {
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            $subrow = null;

            if ($refObject instanceof Materials_Model_Material) {
                $subrow = $row->findDependentRow($this->_material2CategoryTableClass, 'category', array(
                    'material_id = ?' => $refObject->getId(),
                ));
            }

            if ($subrow) {
                return $subrow->delete();
            } else {
                throw new Zend_Exception('Undefined reference to object '.get_class($refObject));
            }
        }
    }

	function getMaterials(Materials_Model_Category $object,
						  $where = null, $order = null, $limit = null, $offset = null, $offsetByPage = false)
	{
		if (true == $offsetByPage) {
            $offset = $this->getPageOffset($limit, $offset);
        }

		$row = $object->getData();
		if ($row instanceof Workset_Db_Table_Row) {
			$select = $this->_getTable()->prepareSelect( $where, $order, $limit, $offset );
			$rowset = $row->findManyToManyRowset(
				$this->_materialTableClass,
				$this->_material2CategoryTableClass,
				'category',
				'material',
				$select
			);

			return $this->getIterator($rowset, array(
                'countRows' => $this->_countAllRecords,
                'filter' => $select,
				'objectClass' => $this->_materialObjectClass,
				'storage' => null
            ));
		}
	}

    function materialsCount(Materials_Model_Category $object, $where = null) {

        if ($where) {
            $where = (array)$where;
        } else {
            $where = array();
        }

        $where['i.category_id = ?'] = $object->getId();

        $table = $this->_getTable($this->_materialTableClass);
		$refTable = $this->_getTable($this->_material2CategoryTableClass);

        $select = $table->getAdapter()->select();

        $select->from(
            array('m' => $table->info(Zend_Db_Table_Abstract::NAME)), array('cnt' => new Zend_Db_Expr('COUNT(*)'))
        );

        $select->join(
            array('i' => $refTable->info(Zend_Db_Table_Abstract::NAME)),
            'm.id = i.material_id',
            array()
        );

        foreach ($where as $key => $value) {
            if (is_int($key)) {
                $select->where($value);
            } else {
                $select->where($key, $value);
            }
        }

        return $table->getAdapter()->query($select)->fetchColumn();

    }

	function getCategoryMaterials($diff = null, $intersect = null, $where = null, $order = null,
                                  $limit = null, $offset = null, $offsetByPage = false)
    {
		if (true == $offsetByPage) {
            $offset = $this->getPageOffset($limit, $offset);
        }

		$where = (array)$where;
		$diffWhere = array();
		$intersectWhere = array();

		$table = $this->_getTable($this->_materialTableClass);
		$refTable = $this->_getTable($this->_material2CategoryTableClass);

		if (null !== $diff) {
			if (!$diff instanceof Workset_Model_Object_Iterator_Abstract) {
				$diff = array_map('intval', (array)$diff);
			} else {
				$diff = $diff->toArray('id');
			}
			$diffWhere['category_id in(?)'] = array_values($diff);
		}

		if (null !== $intersect) {
			if (!$intersect instanceof Workset_Model_Object_Iterator_Abstract) {
				$intersect = array_map('intval', (array)$intersect);
			} else {
				$intersect = $intersect->toArray('id');
			}
			$intersectWhere['category_id in(?)'] = array_values($intersect);
		}

		if ($diffWhere) {

			$diffSelect = $refTable->select(Zend_Db_Table_Abstract::SELECT_WITHOUT_FROM_PART);
			$diffSelect->from(
				array($refTable->info(Zend_Db_Table_Abstract::NAME)),
				array('material_id')

			)->where(key($diffWhere), current($diffWhere));

			$where[] = 'id not in('.$diffSelect->assemble().')';
		}

		if ($intersectWhere) {
			$intersectSelect = $refTable->select(Zend_Db_Table_Abstract::SELECT_WITHOUT_FROM_PART);
			$intersectSelect->from(
				array($refTable->info(Zend_Db_Table_Abstract::NAME)),
				array('material_id')

			)->where(key($intersectWhere), current($intersectWhere));

			$where[] = 'id in('.$intersectSelect->assemble().')';
		}

        $select = $table->prepareSelect($where, $order, $limit, $offset);

        $rowset = $table->fetchAll($select);

        return $this->getIterator($rowset, array(
            'countRows' => $this->_countAllRecords,
            'filter' => $select,
			'objectClass' => $this->_materialObjectClass,
            'storage' => null
        ));
	}

	function getCatalogueCategoryMaterials($diffCatalogue = null, $intersectCatalogue = null, $diff = null, $intersect = null, $where = null, $order = null, $limit = null, $offset = null, $offsetByPage = false) {

		$where = (array)$where;
		$diffWhere = array();
		$intersectWhere = array();

		$refTable = $this->_getTable($this->_object2CatalogueCategoryTableClass);

		if (null !== $diffCatalogue) {
			if (!$diffCatalogue instanceof Workset_Model_Object_Iterator_Abstract) {
				$diffCatalogue = array_map('intval', (array)$diffCatalogue);
			} else {
				$diffCatalogue = $diffCatalogue->toArray('id');
			}
			$diffWhere['category_id in(?)'] = array_values($diffCatalogue);
		}

		if (null !== $intersectCatalogue) {
			if (!$intersectCatalogue instanceof Workset_Model_Object_Iterator_Abstract) {
				$intersectCatalogue = array_map('intval', (array)$intersectCatalogue);
			} else {
				$intersectCatalogue = $intersectCatalogue->toArray('id');
			}
			$intersectWhere['category_id in(?)'] = array_values($intersectCatalogue);
		}

		if ($diffWhere) {

			$diffSelect = $refTable->select(Zend_Db_Table_Abstract::SELECT_WITHOUT_FROM_PART);
			$diffSelect->from(
				array($refTable->info(Zend_Db_Table_Abstract::NAME)),
				array('material_id')

			)->where(key($diffWhere), current($diffWhere));

			$where[] = 'id not in('.$diffSelect->assemble().')';
		}

		if ($intersectWhere) {
			$intersectSelect = $refTable->select(Zend_Db_Table_Abstract::SELECT_WITHOUT_FROM_PART);
			$intersectSelect->from(
				array($refTable->info(Zend_Db_Table_Abstract::NAME)),
				array('material_id')

			)->where(key($intersectWhere), current($intersectWhere));

			$where[] = 'id in('.$intersectSelect->assemble().')';
		}

       	return $this->getCategoryMaterials( $diff, $intersect, $where, $order, $limit, $offset, $offsetByPage);
	}

}
